/*
 * This source code is part of TWaver 4.0
 *
 * Serva Software PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
 * Copyright 2002 - 2011 Serva Software. All rights reserved.
 */

package demo.network.miscellaneous.instrument.elementui;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.RenderingHints;
import java.awt.Shape;
import java.awt.geom.Ellipse2D;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;

import demo.network.miscellaneous.instrument.element.Clock;

import twaver.AlarmSeverity;
import twaver.TWaverConst;
import twaver.TWaverUtil;
import twaver.network.TNetwork;
import twaver.network.ui.BorderUI;
import twaver.network.ui.EditableBorderUI;
import twaver.network.ui.ResizableNodeUI;

public class ClockUI extends ResizableNodeUI {
	
	public ClockUI(TNetwork network, Clock clock) {
		super(network, clock);
	}
	
    public void paintBody(Graphics2D g) {
        g.setStroke(TWaverConst.DOUBLE_WIDTH_STROKE);
        Object oldAntialiasValue = g.getRenderingHint(RenderingHints.KEY_ANTIALIASING);
        g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        
        Clock clock = (Clock)this.getElement();

        // get position
        final Point location = clock.getLocation();
        final Dimension size = clock.getSize();
        final int x = location.x;
        final int y = location.y;
        final int width = size.width;
        final int height = size.height;
        final int xcenter = x + width / 2;
        final int ycenter = y + height / 2;
        
        // draw clock frame
        g.setColor(Color.blue);
        g.drawArc(x, y, width, height, 0, 360);
        g.setColor(Color.darkGray);
        g.fillArc(x+1, y+1, width-1, height-1, 0, 360);
        
        // draw the circle and numbers
        g.setColor(Color.white);
        g.setFont(TWaverUtil.getFont(Font.ITALIC, 12));
        g.drawString("9", xcenter - width/2 + 4, ycenter + 3); 
        g.drawString("3", xcenter + width/2 - 8, ycenter + 3);
        g.drawString("12", xcenter - 6, ycenter - height/2 + 12);
        g.drawString("6", xcenter - 3, ycenter + height/2 - 3);

        // get time
        Date time = (Date)clock.getClientProperty(Clock.CLOCKTIME);
        if(time == null){
        	return;
        }

        Calendar calendar = GregorianCalendar.getInstance();
        calendar.setTime(time);

        // set position of the ends of the hands
        int length = Math.min(width, height)/2;
        if(length < 2){
        	length = 2;
        }
        final int s = calendar.get(Calendar.SECOND);
        final int m = calendar.get(Calendar.MINUTE);
        final int h = calendar.get(Calendar.HOUR_OF_DAY);
        final int xs = (int) (Math.cos(s * Math.PI / 30 - Math.PI / 2) * length * 0.85 + xcenter);
        final int ys = (int) (Math.sin(s * Math.PI / 30 - Math.PI / 2) * length * 0.85 + ycenter);
        final int xm = (int) (Math.cos(m * Math.PI / 30 - Math.PI / 2) * length * 0.7 + xcenter);
        final int ym = (int) (Math.sin(m * Math.PI / 30 - Math.PI / 2) * length * 0.7 + ycenter);
        final int xh = (int) (Math.cos((h*30 + m / 2) * Math.PI / 180 - Math.PI / 2) * length * 0.6 + xcenter);
        final int yh = (int) (Math.sin((h*30 + m / 2) * Math.PI / 180 - Math.PI / 2) * length * 0.6 + ycenter);

        // Draw date and hands
        g.setColor(Color.green);
        g.drawLine(xcenter, ycenter, xs, ys);
        g.setColor(Color.green);
        g.drawLine(xcenter, ycenter-1, xm, ym);
        g.drawLine(xcenter-1, ycenter, xm, ym);
        g.drawLine(xcenter, ycenter-1, xh, yh);
        g.drawLine(xcenter-1, ycenter, xh, yh);
        
        g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, oldAntialiasValue);
        
    }

	public boolean contains(int x, int y) {
		Rectangle rect = element.getBounds();
		
		// whether in circle area
		Shape shape = new Ellipse2D.Double(rect.x, rect.y, rect.width, rect.height);
		if(shape.contains(x, y)){
			return true;
		}
		
        //whether in attachment area.
		return this.containInAttachments(x, y);
	}
    
    /**
     * Get the hotspot location. Using this to determines where
     * to paint attachments.
     * @return the hotspot point.
     */
    public Point getHotspot(){
    	Rectangle bounds = element.getBounds();
    	Double value = (Double)element.getClientProperty(Clock.HOTSPOT);
    	return getEllipseHostPoint(bounds.x, bounds.y, bounds.width, bounds.height, value.doubleValue());
    }
	
	public static Point getEllipseHostPoint(double x, double y, double w, double h, double rate){
		rate = rate / 2;
		Point point = new Point();
		point.x = (int)(x + w * 0.5 + w * rate);
		point.y = (int)(y + h / 2 - Math.sqrt(0.25 - rate * rate) * h);
		return point;
	}
    
    public void paintStateOutline(Graphics2D g2d) {
        // if have propagate severity paint the alarm propagate color.
    	AlarmSeverity severity = element.getAlarmState().getPropagateSeverity();
        if (severity != null) {
            Rectangle bounds = element.getBounds();
            bounds.grow(3, 3);
            
            g2d.setStroke(TWaverUtil.createStroke(4));
            g2d.setColor(severity.getColor());
            
    		Object oldHinds = g2d.getRenderingHint(RenderingHints.KEY_ANTIALIASING);
    		g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
            g2d.drawArc(bounds.x, bounds.y, bounds.width, bounds.height, 0, 360);
            g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, oldHinds);
        }
	}

	public BorderUI getBorder() {
        if (this.getNetwork().isResizable(element)) {
        	if(this.editableBorder == null){
        		this.editableBorder = new EditableBorderUI(this);
        	}
            return editableBorder;
        } else {
        	if(this.defaultBorder == null){
        		this.defaultBorder = new ClockBorderUI(this);
        	}
            return defaultBorder;
        }
    }
	

}